/*
 *  Copyright (C) 2010 glauco
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.common.abstracts;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import org.balisunrise.application.Application;
import org.balisunrise.common.ActionCollection;
import org.balisunrise.common.ActionProvider;
import org.balisunrise.common.Basic;
import org.balisunrise.common.Children;
import org.balisunrise.common.Event;
import org.balisunrise.common.VisualEntity;
import org.balisunrise.common.defaults.DefaultChildren;
import org.balisunrise.common.defaults.VEAUtil;

/**
 *
 * @author glauco
 */
public abstract class AbstractBasic implements Basic{

    /**
     * Proprietário deste Basic.
     */
    protected Basic owner;

    /**
     * Nome para este Basic.
     */
    protected String name;

    /**
     * Basics em que este Basic é proprietário.
     */
    protected Children children;

    /**
     * Modo de transação.
     */
    protected int mode;

    /**
     * Property Change Support para disparar eventos das alterações das
     * propriedades de quaquer Basic.
     */
    protected PropertyChangeSupport changeSupport =
            new PropertyChangeSupport(this);

    @Override
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.addPropertyChangeListener(listener);
    }

    @Override
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.removePropertyChangeListener(listener);
    }

    @Override
    public Basic getOwner() {
        return owner;
    }

    @Override
    public void setOwner(Basic owner) {
        Basic oldOwner = this.owner;
        this.owner = owner;
        changeSupport.firePropertyChange("owner", oldOwner, owner);
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        String oldName = this.name;
        this.name = name;
        changeSupport.firePropertyChange("name",oldName,name);
    }
    
    /**
     * Atribui o Modo de transação.
     * Dependendo do modo pode existir diferentes formas de exibição, regras,
     * ações e eventos.
     * @param mode Modo referente a interface
     * {@link org.balisunrise.common.Mode}.
     *
     * @see org.balisunrise.common.Mode
     */
    @Override
    public void setMode(int mode){

        // modos válidos
        if (mode < 0 && mode > 4)
            return ;

        int old = this.mode;
        this.mode = mode;

        for (Basic b : getChildren().getBasics()) {
            if (b != null)
                b.setMode(mode);
        }

        changeSupport.firePropertyChange("mode", old, mode);
    }

    /**
     * A ActionCollection mantém as instâncias dos mapas de ação de uma
     * entidade.<br>
     * As ações do um Basic pegam a ActionCollection do Basic para pegar a
     * instância do mapa de ação referênte a ação.<br>
     * Para que exista apenas uma instância do mapa de ações, o Basic sempre
     * requer a seu proprietário a ActionCollection.<br>
     * Apenas a VisualEntity do topo da arvore ter uma instância de
     * ActionCollection.
     *
     * @return A instância do Basic do topo da árvore de proprietários.
     */
    @Override
    public ActionCollection getActionCollection(){
        VisualEntity ve = VEAUtil.getTopVisualEntity(this);
        ActionProvider ap = Application.get()
                .getActionMapManager()
                .getActionProvider(ve.getEntityClass());
        return ap.getActionCollection(ve);
    }

    @Override
    public void actionPerformed(Event evt){
        if(owner != null){
            evt.addOwner(this);
            owner.actionPerformed(evt);
        }
    }

    @Override
    public Children getChildren() {
        if (children == null)
            setChildren(new DefaultChildren(this));
        return children;
    }

    protected void setChildren(Children children){
        Children old = this.children;
        this.children = children;
        changeSupport.firePropertyChange("children", old, children);
    }
}
